package com.baikeyang.commons.flyway;

import org.flywaydb.core.Flyway;

import javax.sql.DataSource;

/**
 * Created with IDEA
 * @ClassName MigrationMySql
 * @Description TODO
 * @Author BaiKeyang
 * @Computer lenovo
 * @Date 2018/9/14 10:47
 * @Version 1.0.0
 */
public class MigrationMySql {

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 指令介绍：
     * Migrate
     * Migrate是指把数据库Schema迁移到最新版本，是Flyway工作流的核心功能，Flyway在Migrate时会检查Metadata(元数据)表，如果不存在会创建Metadata表，Metadata表主要用于记录版本变更历史以及Checksum之类的。
     * Migrate时会扫描指定文件系统或Classpath下的Migrations(可以理解为数据库的版本脚本)，并且会逐一比对Metadata表中的已存在的版本记录，如果有未应用的Migrations，Flyway会获取这些Migrations并按次序Apply到数据库中，否则不需要做任何事情。另外，通常在应用程序启动时应默认执行Migrate操作，从而避免程序和数据库的不一致性。
     *
     * Clean
     * Clean操作在开发和测试阶段是非常有用的，它能够帮助快速有效地更新和重新生成数据库表结构，但特别注意的是：不应在`Production`的数据库上使用！
     *
     * Info
     * Info用于打印所有Migrations的详细和状态信息，其实也是通过Metadata表和Migrations完成的，下图很好地示意了Info打印出来的信息。
     * Info能够帮助快速定位当前的数据库版本，以及查看执行成功和失败的Migrations。
     *
     * Validate
     * Validate是指验证已经Apply的Migrations是否有变更，Flyway是默认是开启验证的。
     * Validate原理是对比Metadata表与本地Migrations的Checksum值，如果值相同则验证通过，否则验证失败，从而可以防止对已经Apply到数据库的本地Migrations的无意修改。
     *
     * Baseline
     * Baseline针对已经存在Schema结构的数据库的一种解决方案，即实现在非空数据库中新建Metadata表，并把Migrations应用到该数据库。
     * Baseline可以应用到特定的版本，这样在已有表结构的数据库中也可以实现添加Metadata表，从而利用Flyway进行新Migrations的管理了。
     *
     * Repair
     * Repair操作能够修复Metadata表，该操作在Metadata表出现错误时是非常有用的。
     * Repair会修复Metadata表的错误，通常有两种用途：
     *  *移除失败的Migration记录，该问题只是针对不支持DDL事务的数据库。
     *  *重新调整已经应用的Migratons的Checksums值，比如：某个Migratinon已经被应用，但本地进行了修改，又期望重新应用并调整Checksum值，不过尽量不要这样操作，否则可能造成其它环境失败。
     *
     */
    public void migrate() {

        //初始化flyway类
        Flyway flyway = new Flyway();

        //设置加载数据库的相关配置信息
        flyway.setDataSource(dataSource);

        //设置存放flyway metadata数据的表名，默认"schema_version"，可不写
        //flyway.setTable("schema_version");

        //设置flyway扫描sql升级脚本、java升级脚本的目录路径或包路径，默认"db/migration"，可不写
        //flyway.setLocations("db/migration");

        //设置sql脚本文件的编码，默认"UTF-8"，可不写
        flyway.setEncoding("UTF-8");

        // 针对数据库在同一段时间有修改，但不会造成冲突的情况，通常实际项目中主要存在这样的情况
        // 那可以设置flyway.out-of-order=true，这样允许当v1和v3已经被应用后，v2出现时同样也可以被应用
        flyway.setOutOfOrder(false);

        try {
            flyway.clean();
            //flyway.setValidateOnMigrate(true);
            //flyway.setCleanDisabled(true);
            flyway.setBaselineOnMigrate(false);
            // 开始执行
            flyway.migrate();
        } catch (Exception e) {
            flyway.repair();
            e.printStackTrace();
        }

    }

}
